Yii 提供了一組可以用來顯示資料的 小工具。雖然 DetailView 小工具可以用來顯示單一記錄的資料,但 ListView 和 GridView 可以用來顯示資料記錄的列表或表格,並提供諸如分頁、排序和篩選等功能。
DetailView 小工具顯示單一資料 模型 的詳細資訊。
它最適合用於以常規格式顯示模型(例如,每個模型屬性都顯示為表格中的一行)。模型可以是 yii\base\Model 的實例或子類別,例如 active record 或關聯陣列。
DetailView 使用 $attributes 屬性來決定應顯示哪些模型屬性以及應如何格式化它們。有關可用的格式化選項,請參閱格式化器章節。
DetailView 的典型用法如下
echo DetailView::widget([
'model' => $model,
'attributes' => [
'title', // title attribute (in plain text)
'description:html', // description attribute formatted as HTML
[ // the owner name of the model
'label' => 'Owner',
'value' => $model->owner->name,
'contentOptions' => ['class' => 'bg-red'], // HTML attributes to customize value tag
'captionOptions' => ['tooltip' => 'Tooltip'], // HTML attributes to customize label tag
],
'created_at:datetime', // creation date formatted as datetime
],
]);
請記住,與處理一組模型的 yii\widgets\GridView 不同,DetailView 僅處理一個模型。因此,大多數時候不需要使用閉包,因為 $model
是唯一要顯示的模型,並且在視圖中作為變數可用。
但是,在某些情況下,使用閉包可能很有用。例如,當指定 visible
並且您希望在評估為 false
時防止 value
計算時
echo DetailView::widget([
'model' => $model,
'attributes' => [
[
'attribute' => 'owner',
'value' => function ($model) {
return $model->owner->name;
},
'visible' => \Yii::$app->user->can('posts.owner.view'),
],
],
]);
ListView 小工具用於顯示來自 資料提供器 的資料。每個資料模型都使用指定的 視圖檔案 呈現。由於它提供了諸如分頁、排序和篩選等現成功能,因此它既可以用於向終端使用者顯示資訊,也可以用於建立資料管理 UI。
典型的用法如下
use yii\widgets\ListView;
use yii\data\ActiveDataProvider;
$dataProvider = new ActiveDataProvider([
'query' => Post::find(),
'pagination' => [
'pageSize' => 20,
],
]);
echo ListView::widget([
'dataProvider' => $dataProvider,
'itemView' => '_post',
]);
_post
視圖檔案可能包含以下內容
<?php
use yii\helpers\Html;
use yii\helpers\HtmlPurifier;
?>
<div class="post">
<h2><?= Html::encode($model->title) ?></h2>
<?= HtmlPurifier::process($model->text) ?>
</div>
在上面的視圖檔案中,目前的資料模型以 $model
的形式提供。此外,還提供以下變數
$key
:混合型別,與資料項目關聯的鍵值。$index
:整數,資料項目在資料提供器傳回的項目陣列中的從零開始的索引。$widget
:ListView,此小工具實例。如果您需要將其他資料傳遞到每個視圖,則可以使用 $viewParams 屬性來傳遞鍵值對,如下所示
echo ListView::widget([
'dataProvider' => $dataProvider,
'itemView' => '_post',
'viewParams' => [
'fullView' => true,
'context' => 'main-page',
// ...
],
]);
然後這些也將作為視圖中的變數提供。
資料網格或 GridView 是 Yii 最強大的小工具之一。如果您需要快速建構系統的管理部分,它非常有用。它從 資料提供器 取得資料,並使用一組 欄 呈現每一行,以表格的形式呈現資料。
表格的每一行代表單一資料項目的資料,而欄通常代表項目的屬性(某些欄可能對應於屬性或靜態文字的複雜表示式)。
使用 GridView 所需的最少程式碼如下
use yii\grid\GridView;
use yii\data\ActiveDataProvider;
$dataProvider = new ActiveDataProvider([
'query' => Post::find(),
'pagination' => [
'pageSize' => 20,
],
]);
echo GridView::widget([
'dataProvider' => $dataProvider,
]);
上面的程式碼首先建立資料提供器,然後使用 GridView 顯示從資料提供器取得的每一行中的每個屬性。顯示的表格配備了現成的排序和分頁功能。
網格表格的欄在 yii\grid\Column 類別方面進行組態,這些類別在 GridView 組態的 columns 屬性中組態。根據欄型別和設定,這些類別能夠以不同的方式呈現資料。預設類別是 yii\grid\DataColumn,它代表模型屬性,並且可以按其排序和篩選。
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
// Simple columns defined by the data contained in $dataProvider.
// Data from the model's column will be used.
'id',
'username',
// More complex one.
[
'class' => 'yii\grid\DataColumn', // can be omitted, as it is the default
'value' => function ($data) {
return $data->name; // $data['name'] for array data, e.g. using SqlDataProvider.
},
],
],
]);
請注意,如果未指定組態的 columns 部分,Yii 會嘗試顯示資料提供器模型的所有可能欄。
網格欄可以使用不同的欄類別進行自訂
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
[
'class' => 'yii\grid\SerialColumn', // <-- here
// you may configure additional properties here
],
除了我們將在下面回顧的 Yii 提供的欄類別之外,您還可以建立自己的欄類別。
每個欄類別都從 yii\grid\Column 擴充,因此在組態網格欄時,您可以設定一些常用選項。
content 允許您傳遞有效的 PHP 回呼,該回呼將傳回行的資料。格式如下
function ($model, $key, $index, $column) {
return 'a string';
}
您可以通過將陣列傳遞到以下位置來指定各種容器 HTML 選項
資料欄 用於顯示和排序資料。它是預設欄型別,因此在使用它時可以省略指定類別。
資料欄的主要設定是其 format 屬性。其值對應於 formatter
應用程式元件 中的方法,預設為 Formatter
echo GridView::widget([
'columns' => [
[
'attribute' => 'name',
'format' => 'text'
],
[
'attribute' => 'birthday',
'format' => ['date', 'php:Y-m-d']
],
'created_at:datetime', // shortcut format
[
'label' => 'Education',
'attribute' => 'education',
'filter' => ['0' => 'Elementary', '1' => 'Secondary', '2' => 'Higher'],
'filterInputOptions' => ['prompt' => 'All educations', 'class' => 'form-control', 'id' => null]
],
],
]);
在上面,text
對應於 yii\i18n\Formatter::asText()。欄的值作為第一個引數傳遞。在第二個欄定義中,date
對應於 yii\i18n\Formatter::asDate()。欄的值再次作為第一個引數傳遞,而 'php:Y-m-d' 用作第二個引數值。
有關可用格式化器的列表,請參閱關於資料格式化的章節。
對於組態資料欄,還有一個快捷方式格式,在 columns 的 API 文件中進行了描述。
使用 filter 和 filterInputOptions 來控制篩選器輸入的 HTML。
預設情況下,欄標題由 yii\data\Sort::link() 呈現。可以使用 yii\grid\Column::$header 進行調整。若要變更標題文字,您應該像上面的範例中一樣設定 yii\grid\DataColumn::$label。預設情況下,標籤將從資料模型中填入。有關更多詳細資訊,請參閱 yii\grid\DataColumn::getHeaderCellLabel()。
操作欄 顯示每一行的操作按鈕,例如更新或刪除。
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
[
'class' => 'yii\grid\ActionColumn',
// you may configure additional properties here
],
您可以組態的可用屬性為
{view}
將被回呼 buttons['view']
的結果取代。如果找不到回呼,則權杖將被空字串取代。預設權杖為 {view} {update} {delete}
。buttons 是一個按鈕呈現回呼陣列。陣列鍵是按鈕名稱(不帶大括號),值是相應的按鈕呈現回呼。回呼應使用以下簽名
function ($url, $model, $key) {
// return the button HTML code
}
在上面的程式碼中,$url
是欄為按鈕建立的 URL,$model
是為目前行呈現的模型物件,$key
是資料提供器陣列中模型的鍵。
visibleButtons 是一個用於每個按鈕的可見性條件陣列。陣列鍵是按鈕名稱(不帶大括號),值是布林值 true
/false
或匿名函式。當此陣列中未指定按鈕名稱時,預設情況下將顯示該按鈕。回呼必須使用以下簽名
function ($model, $key, $index) {
return $model->status === 'editable';
}
或者您可以傳遞布林值
[
'update' => \Yii::$app->user->can('update')
]
核取方塊欄 顯示核取方塊欄。
若要將 CheckboxColumn 新增至 GridView,請將其新增至 columns 組態,如下所示
echo GridView::widget([
'id' => 'grid',
'dataProvider' => $dataProvider,
'columns' => [
// ...
[
'class' => 'yii\grid\CheckboxColumn',
// you may configure additional properties here
],
],
使用者可以按一下核取方塊以選取網格的行。可以透過呼叫以下 JavaScript 程式碼來取得選取的行
var keys = $('#grid').yiiGridView('getSelectedRows');
// keys is an array consisting of the keys associated with the selected rows
序號欄 呈現從 1
開始並向前推進的行號。
用法與以下一樣簡單
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'], // <-- here
// ...
注意:本節正在開發中。
為了篩選資料,GridView 需要一個 模型,該模型代表搜尋條件,搜尋條件通常取自 GridView 表格中的篩選欄位。使用 active record 時的常見做法是建立一個搜尋模型類別,該類別提供所需的功能(可以由 Gii 為您產生)。此類別定義驗證規則,以在 GridView 表格上顯示篩選控制項,並提供一個 search()
方法,該方法將傳回資料提供器,其中包含已調整的查詢,用於處理搜尋條件。
若要為 Post
模型新增搜尋功能,我們可以建立一個 PostSearch
模型,如以下範例所示
<?php
namespace app\models;
use Yii;
use yii\base\Model;
use yii\data\ActiveDataProvider;
class PostSearch extends Post
{
public function rules()
{
// only fields in rules() are searchable
return [
[['id'], 'integer'],
[['title', 'creation_date'], 'safe'],
];
}
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
public function search($params)
{
$query = Post::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
// load the search form data and validate
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
// adjust the query by adding the filters
$query->andFilterWhere(['id' => $this->id]);
$query->andFilterWhere(['like', 'title', $this->title])
->andFilterWhere(['like', 'creation_date', $this->creation_date]);
return $dataProvider;
}
}
您可以在控制器中使用此函式來取得 GridView 的 dataProvider
$searchModel = new PostSearch();
$dataProvider = $searchModel->search(Yii::$app->request->get());
return $this->render('myview', [
'dataProvider' => $dataProvider,
'searchModel' => $searchModel,
]);
然後在視圖中,您可以將 $dataProvider
和 $searchModel
指派給 GridView
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
// ...
],
]);
大多數時候,使用 GridView 標題篩選器就足夠了,但是如果您需要獨立的篩選表單,您也可以輕鬆地新增它。您可以建立具有以下內容的部分視圖 _search.php
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model app\models\PostSearch */
/* @var $form yii\widgets\ActiveForm */
?>
<div class="post-search">
<?php $form = ActiveForm::begin([
'action' => ['index'],
'method' => 'get',
]); ?>
<?= $form->field($model, 'title') ?>
<?= $form->field($model, 'creation_date') ?>
<div class="form-group">
<?= Html::submitButton('Search', ['class' => 'btn btn-primary']) ?>
<?= Html::submitButton('Reset', ['class' => 'btn btn-default']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
並將其包含在 index.php
視圖中,如下所示
<?= $this->render('_search', ['model' => $searchModel]) ?>
注意:如果您使用 Gii 產生 CRUD 程式碼,則預設情況下會產生獨立的篩選表單 (
_search.php
),但在index.php
視圖中會註解掉。取消註解它,就可以使用了!
當您需要按不在 GridView 中顯示的欄位進行篩選或進行特殊篩選條件(例如日期範圍)時,獨立篩選表單非常有用。為了按日期範圍篩選,我們可以將非 DB 屬性 createdFrom
和 createdTo
新增到搜尋模型
class PostSearch extends Post
{
/**
* @var string
*/
public $createdFrom;
/**
* @var string
*/
public $createdTo;
}
在 search()
方法中擴充查詢條件,如下所示
$query->andFilterWhere(['>=', 'creation_date', $this->createdFrom])
->andFilterWhere(['<=', 'creation_date', $this->createdTo]);
並將代表性欄位新增到篩選表單
<?= $form->field($model, 'creationFrom') ?>
<?= $form->field($model, 'creationTo') ?>
在 GridView 中顯示 active record 時,您可能會遇到顯示相關欄的值的情況,例如文章作者的姓名,而不是僅顯示他的 id
。您可以透過在 yii\grid\GridView::$columns 中將屬性名稱定義為 author.name
來執行此操作,當 Post
模型具有名為 author
的關聯,並且作者模型具有屬性 name
時。然後,GridView 將顯示作者的姓名,但預設情況下不啟用排序和篩選。您必須調整上一節中介紹的 PostSearch
模型,以新增此功能。
若要在相關欄上啟用排序,您必須聯結相關表格,並將排序規則新增至資料提供器的排序元件
$query = Post::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
// join with relation `author` that is a relation to the table `users`
// and set the table alias to be `author`
$query->joinWith(['author' => function($query) { $query->from(['author' => 'users']); }]);
// since version 2.0.7, the above line can be simplified to $query->joinWith('author AS author');
// enable sorting for the related column
$dataProvider->sort->attributes['author.name'] = [
'asc' => ['author.name' => SORT_ASC],
'desc' => ['author.name' => SORT_DESC],
];
// ...
篩選也需要如上所述的 joinWith 呼叫。您還需要在屬性和規則中定義可搜尋的欄,如下所示
public function attributes()
{
// add related fields to searchable attributes
return array_merge(parent::attributes(), ['author.name']);
}
public function rules()
{
return [
[['id'], 'integer'],
[['title', 'creation_date', 'author.name'], 'safe'],
];
}
然後在 search()
中,您只需新增另一個篩選條件
$query->andFilterWhere(['LIKE', 'author.name', $this->getAttribute('author.name')]);
資訊:在上面,我們對關聯名稱和表格別名使用相同的字串;但是,當您的別名和關聯名稱不同時,您必須注意在何處使用別名,以及在何處使用關聯名稱。一個簡單的規則是在每個用於建構資料庫查詢的地方使用別名,在所有其他定義(例如
attributes()
和rules()
等)中使用關聯名稱。例如,如果您對作者關聯表格使用別名
au
,則 joinWith 陳述式如下所示
$query->joinWith(['author au']);
當在關聯定義中定義了別名時,也可以只呼叫
$query->joinWith(['author']);
。別名必須在篩選條件中使用,但屬性名稱保持不變
$query->andFilterWhere(['LIKE', 'au.name', $this->getAttribute('author.name')]);
排序定義也是如此
$dataProvider->sort->attributes['author.name'] = [ 'asc' => ['au.name' => SORT_ASC], 'desc' => ['au.name' => SORT_DESC], ];
此外,當指定排序的 defaultOrder 時,您需要使用關聯名稱而不是別名
$dataProvider->sort->defaultOrder = ['author.name' => SORT_ASC];
資訊:有關
joinWith
和背景中執行的查詢的更多資訊,請查看關於與關聯聯結的 active record 文件。
還有另一種方法可以更快且更有用 - SQL 視圖。例如,如果我們需要顯示包含使用者及其設定檔的 gridview,我們可以透過這種方式執行
CREATE OR REPLACE VIEW vw_user_info AS
SELECT user.*, user_profile.lastname, user_profile.firstname
FROM user, user_profile
WHERE user.id = user_profile.user_id
然後,您需要建立將代表此視圖的 ActiveRecord
namespace app\models\views\grid;
use yii\db\ActiveRecord;
class UserView extends ActiveRecord
{
/**
* {@inheritdoc}
*/
public static function tableName()
{
return 'vw_user_info';
}
public static function primaryKey()
{
return ['id'];
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
// define here your rules
];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
// define here your attribute labels
];
}
}
之後,您可以使用此 UserView active record 和搜尋模型,而無需額外指定排序和篩選屬性。所有屬性都將開箱即用。請注意,此方法有一些優缺點
isActive
、isDeleted
或其他會影響 UI 的方法),您也需要在這個類別中複製它們。您可以在單一頁面上使用多個 GridView,但需要進行一些額外組態,以使其彼此不干擾。當使用 GridView 的多個實例時,您必須為產生的排序和分頁連結組態不同的參數名稱,以便每個 GridView 都有自己的個別排序和分頁。您可以透過設定 dataProvider 的 sort 和 pagination 實例的 sortParam 和 pageParam 來執行此操作。
假設我們要列出 Post
和 User
模型,我們已經在 $userProvider
和 $postProvider
中準備了兩個資料提供器
use yii\grid\GridView;
$userProvider->pagination->pageParam = 'user-page';
$userProvider->sort->sortParam = 'user-sort';
$postProvider->pagination->pageParam = 'post-page';
$postProvider->sort->sortParam = 'post-sort';
echo '<h1>Users</h1>';
echo GridView::widget([
'dataProvider' => $userProvider,
]);
echo '<h1>Posts</h1>';
echo GridView::widget([
'dataProvider' => $postProvider,
]);
Pjax 小工具允許您更新頁面的特定區段,而不是重新載入整個頁面。當使用篩選器時,您可以使用它僅更新 GridView 內容。
use yii\widgets\Pjax;
use yii\grid\GridView;
Pjax::begin([
// PJax options
]);
Gridview::widget([
// GridView options
]);
Pjax::end();
Pjax 也適用於 Pjax 小工具內的連結和 Pjax::$linkSelector 指定的連結。但這對於 ActionColumn 的連結來說可能是一個問題。若要防止這種情況,請在編輯 ActionColumn::$buttons 屬性時,將 HTML 屬性 data-pjax="0"
新增至連結。
自 2.0.5 起,Gii 的 CRUD 產生器有一個名為 $enablePjax
的選項,可以透過 Web 介面或命令列使用。
yii gii/crud --controllerClass="backend\\controllers\PostController" \
--modelClass="common\\models\\Post" \
--enablePjax=1
它會產生一個 Pjax 小工具,用於包裝 GridView 或 ListView 小工具。
發現錯字或您認為此頁面需要改進?
在 github 上編輯 !
在「獨立篩選表單」章節的最後一個程式碼中,我們有一個錯誤
<?= $form->field($model, 'creationFrom') ?> <?= $form->field($model, 'creationTo') ?>
應該是
<?= $form->field($model, 'createdFrom') ?> <?= $form->field($model, 'createdTo') ?>
對我來說,ListView 和 GridView 最有用的事情是透過某種連結或按鈕開啟「詳細」畫面。除了「操作」欄之外,這並沒有真正解決太多問題。大多數時候,您不想要新欄,而只是文字中的連結供他們按一下。我相信上面的其中一件事情可以做到,但真的不清楚是什麼或如何做。
註冊 或 登入 以發表評論。